package com.bosssoft.platform.fasttcc.impl;

import com.bosssoft.platform.fasttcc.*;
import com.bosssoft.platform.fasttcc.assist.TccConnection;
import com.bosssoft.platform.fasttcc.support.CompleteStageHelper;
import com.jfireframework.baseutil.TRACEID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ExecutorService;

public class TccInvokeImpl implements TccInvoke
{
    private final        Object[]            params;
    private final        TccOperation        tccOperation;
    private final        Xid                 completeStageXid;
    private volatile     boolean             completed = false;
    private              LocalTransaction    localTransaction;
    private              CompleteStageHelper helper;
    private              ExecutorService     executorService;
    private static final Logger              LOGGER    = LoggerFactory.getLogger(TccInvokeImpl.class);

    public TccInvokeImpl(Object[] params, TccOperation tccOperation, CompleteStageHelper helper, Xid completeStageXid, ExecutorService executorService)
    {
        this.params = params;
        this.tccOperation = tccOperation;
        this.helper = helper;
        this.completeStageXid = completeStageXid;
        this.executorService = executorService;
    }

    @Override
    public Object[] getParams()
    {
        return params;
    }

    @Override
    public TccOperation getTccOperation()
    {
        return tccOperation;
    }

    @Override
    public Xid getCompleteStageXid()
    {
        return completeStageXid;
    }

    @Override
    public LocalTransaction getAssociatedLocalTransaction()
    {
        return localTransaction;
    }

    @Override
    public void commit(boolean async, final CompleteStageListener listener)
    {
        if (async)
        {
            executorService.submit(new Runnable()
            {
                @Override
                public void run()
                {
                    doCommit(listener);
                }
            });
        }
        else
        {
            doCommit(listener);
        }
    }

    private void doCommit(CompleteStageListener listener)
    {
        String traceId = TRACEID.newTraceId();
        if (tccOperation.getConfirmMethod() != null)
        {
            try
            {
                TccConnection.localTccInvoke.set(TccInvokeImpl.this);
                LOGGER.debug("traceId:{} 准备执行TCC调用:{}的确认分支，执行方法:{}.{}", traceId, completeStageXid, tccOperation.getConfirmClass().getName(), tccOperation.getConfirmMethod().getName());
                helper.invokeMethod(tccOperation.getConfirmMethod(), tccOperation.getConfirmClass(), params);
                completed = true;
                LOGGER.debug("traceId:{} 确认分支执行完毕", traceId);
            }
            catch (Throwable e)
            {
                LOGGER.error("traceId:{} 确认分支执行异常", traceId, e);
            }
            finally
            {
                TccConnection.localTccInvoke.remove();
                if (listener != null)
                {
                    listener.onFinish();
                }
            }
        }
        else
        {
            completed = true;
            TccConnection.localTccInvoke.remove();
            if (listener != null)
            {
                listener.onFinish();
            }
        }
    }

    @Override
    public void rollback(boolean async, final CompleteStageListener listener)
    {
        if (async)
        {
            executorService.submit(new Runnable()
            {
                @Override
                public void run()
                {
                    doRollback(listener);
                }
            });
        }
        else
        {
            doRollback(listener);
        }
    }

    private void doRollback(CompleteStageListener listener)
    {
        String traceId = TRACEID.newTraceId();
        if (tccOperation.getCancelMethod() != null)
        {
            try
            {
                TccConnection.localTccInvoke.set(TccInvokeImpl.this);
                LOGGER.debug("traceId:{} 准备执行TCC调用:{}的回滚分支，执行方法:{}.{}", traceId, completeStageXid, tccOperation.getCancelClass().getName(), tccOperation.getCancelMethod().getName());
                helper.invokeMethod(tccOperation.getCancelMethod(), tccOperation.getCancelClass(), params);
                completed = true;
                LOGGER.debug("traceId:{} 回滚分支执行完毕", traceId);
            }
            finally
            {
                TccConnection.localTccInvoke.remove();
                if (listener != null)
                {
                    listener.onFinish();
                }
            }
        }
        else
        {
            completed = true;
            TccConnection.localTccInvoke.remove();
            if (listener != null)
            {
                listener.onFinish();
            }
        }
    }

    @Override
    public void associateLocalTransaction(LocalTransaction localTransaction)
    {
        this.localTransaction = localTransaction;
    }

    @Override
    public boolean isCompleted()
    {
        return completed;
    }

    @Override
    public void markCompleted()
    {
        completed = true;
    }
}
